import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Scanner;
import java.io.File;
import java.io.FileInputStream;

public class SSCOMDataParser {
    private static final byte[] EXPECTED_FRAME_HEADER = {(byte) 0x57, (byte) 0x53};

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 选择输入方式：文件或手动输入
        System.out.println("请选择数据输入方式：1 - 文件，2 - 手动输入");
        int choice = scanner.nextInt();
        scanner.nextLine(); // 消费换行符

        byte[] packet;
        if (choice == 1) {
            System.out.println("请输入文件路径（如 D:\\study-java\\data.txt）：");
            String filePath = scanner.nextLine();
            packet = readDataFromFile(filePath);
        } else {
            System.out.println("请输入 SSCOM 接收到的十六进制数据（空格分隔，如 57 53 01 ...）：");
            String hexData = scanner.nextLine();
            packet = hexStringToByteArray(hexData);
        }

        if (packet != null && packet.length > 0) {
            System.out.println("开始解析数据包，长度: " + packet.length + " 字节");
            parsePacket(packet);
        } else {
            System.out.println("错误：未能获取有效数据");
        }

        scanner.close();
    }

    // 从文件中读取十六进制数据
    private static byte[] readDataFromFile(String filePath) {
        try (FileInputStream fis = new FileInputStream(new File(filePath))) {
            StringBuilder hexData = new StringBuilder();
            int byteRead;
            while ((byteRead = fis.read()) != -1) {
                hexData.append(String.format("%02X ", byteRead));
            }
            return hexStringToByteArray(hexData.toString().trim());
        } catch (Exception e) {
            System.out.println("文件读取失败: " + e.getMessage());
            return null;
        }
    }

    // 将十六进制字符串转换为字节数组
    private static byte[] hexStringToByteArray(String hexString) {
        String[] hexValues = hexString.split("\\s+");
        byte[] bytes = new byte[hexValues.length];
        try {
            for (int i = 0; i < hexValues.length; i++) {
                bytes[i] = (byte) Integer.parseInt(hexValues[i], 16);
            }
            return bytes;
        } catch (NumberFormatException e) {
            System.out.println("十六进制解析失败: " + e.getMessage());
            return null;
        }
    }

    // 解析数据包
    private static void parsePacket(byte[] packet) {
        ByteBuffer buffer = ByteBuffer.wrap(packet).order(ByteOrder.LITTLE_ENDIAN);
        int offset = 0;

        // 1. 帧头 (2字节)
        byte[] frameHeader = new byte[2];
        buffer.get(frameHeader);
        offset += 2;
        if (!Arrays.equals(frameHeader, EXPECTED_FRAME_HEADER)) {
            System.out.println("错误: 帧头不匹配，预期 0x57 0x53，实际: " + bytesToHex(frameHeader));
            return;
        }
        System.out.println("帧头: " + bytesToHex(frameHeader));

        // 2. 帧类型 (1字节)
        byte frameType = buffer.get();
        offset += 1;
        System.out.println("帧类型: " + (frameType == 0x01 ? "数据帧 (0x01)" : "未知 (" + String.format("%02X", frameType) + ")"));

        // 3. 数据帧长度 (2字节)
        short frameLength = buffer.getShort();
        offset += 2;
        System.out.println("数据帧长度: " + frameLength + " 字节");

        // 4. 采集设备编号 (8字节)
        long deviceSn = buffer.getLong();
        offset += 8;
        System.out.println("采集设备SN: " + deviceSn);

        // 5. 时间戳 (8字节)
        long timestamp = buffer.getLong();
        offset += 8;
        ZonedDateTime localTime = Instant.ofEpochMilli(timestamp).atZone(ZoneId.of("Asia/Shanghai"));
        System.out.println("时间戳: " + timestamp + " ms (" + localTime + ")");

        // 6. 数据项数量 (1字节)
        byte itemCount = buffer.get();
        offset += 1;
        System.out.println("数据项数量: " + (itemCount & 0xFF));

        // 7. 数据项 (N * 6字节 或 N * 10字节)
        for (int i = 0; i < (itemCount & 0xFF); i++) {
            short sensorType = buffer.getShort();
            offset += 2;
            String valueStr;
            if (sensorType % 100 == 0) { // 二级编码为 00，使用 8 字节整数
                long value = buffer.getLong();
                offset += 8;
                valueStr = "值=" + value;
            } else { // 其他编码，使用 4 字节浮点
                float value = buffer.getFloat();
                offset += 4;
                valueStr = "值=" + value;
            }
            System.out.println("数据项 " + (i + 1) + ": 传感器类型=" + sensorType + ", " + valueStr);
        }

        // 8. 滚动校验 (1字节)
        byte rollChecksum = buffer.get();
        offset += 1;
        System.out.println("滚动校验: " + String.format("%02X", rollChecksum));

        // 9. 累加校验 (1字节)
        byte receivedChecksum = buffer.get();
        byte[] dataToCheck = Arrays.copyOfRange(packet, 0, packet.length - 1);
        byte calculatedChecksum = calculateChecksum(dataToCheck);
        System.out.println("累加校验: 接收值=" + String.format("%02X", receivedChecksum) +
                ", 计算值=" + String.format("%02X", calculatedChecksum) +
                (receivedChecksum == calculatedChecksum ? " (校验通过)" : " (校验失败)"));

        // 验证数据包长度
        if (offset + 2 != packet.length) {
            System.out.println("警告: 数据包长度异常，预期 " + (offset + 2) + " 字节，实际 " + packet.length + " 字节");
        }
    }

    private static byte calculateChecksum(byte[] data) {
        int sum = 0;
        for (byte b : data) {
            sum += (b & 0xFF);
        }
        return (byte) (sum & 0xFF);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }
}